<template>
    <div>
        <h2>演示数组更新(原数组会被修改)</h2>
        <button v-on:click="resetBooks">重置数组</button>
        <button v-on:click="addBook">增加《effective Java》这本书</button>
        <button v-on:click="removeBook">删除《effective Java》这本书</button>
        <button v-on:click="popBook">pop《effective Java》这本书</button>
        <button v-on:click="shiftBook">从首行删除《effective Java》这本书</button>
        <button v-on:click="unshiftBook">在首行新增《effective Java》这本书</button>
        <button v-on:click="spliceBook">在第2行和3行之间新增《effective Java》这本书</button>
        <button v-on:click="sortBook">排序</button>
        <button v-on:click="reverseBook">反转顺序</button>
        <button v-on:click="tryChangeBookByIndexNoWork">通过数组索引设置项(无效)</button>
        <button v-on:click="changeBookByIndex">通过数组索引设置项</button>
        <button v-on:click="tryChangeBooksLengthNoWork">通过length清空数组(无效)</button>

        <ul>
            <li v-for="(book, index) in books">{{ index }} , {{ book.name }}</li>
        </ul>

        <br/>
        <br/>
        <h2>演示数组筛选(原数组不会被修改)</h2>
        <button v-on:click="resetBooks2">重置数组</button>
        <button v-on:click="filterJavascript">过滤Javascript</button>
        <ul>
            <li v-for="(book, index) in books2">{{ index }} , {{ book.name }}</li>
        </ul>


        <br/>
        <br/>
        <h2>演示通过计算属性筛选数组(原数组不会被修改)</h2>
        <ul>
            <li v-for="(book, index) in filterBooks">{{ index }} , {{ book.name }}</li>
        </ul>
    </div>
</template>
<script>
    export default {
        data () {
            return {
                effectiveJava: "《effective Java》",
                books: [
                    {name: '《Vue.js》'},
                    {name: '《Javascript》'},
                    {name: '《Java》'}
                ],
                books2: [
                    {name: '《Vue2.js》'},
                    {name: '《Javascript2》'},
                    {name: '《Java2》'}
                ]
            }
        },
        /**
         * 计算属性
         */
        computed: {
            /**
             * 计算属性是有缓存的，只有当计算属性所依赖的数据发生变化时，才会重新取值
             * 比 methods 中的方法效率更好
             * @returns {string}
             */
            "filterBooks": function () {
                return this.books2.filter(function (item) {
                    return item.name.match(/Javascript/);
                })
            }
        },
        created() {

        },
        mounted() {

        },
        methods: {
            resetBooks() {
                this.books = [
                    {name: '《Vue.js》'},
                    {name: '《Javascript》'},
                    {name: '《Java》'}
                ]
            },
            resetBooks2() {
                this.books2 = [
                    {name: '《Vue.js》'},
                    {name: '《Javascript》'},
                    {name: '《Java》'}
                ]
            },
            addBook() {
                let bookName = this.effectiveJava;
                let isExist = this.books.some(function(item){
                    return item.name === bookName;
                })

                /**
                 * 如果已经存在这本数，就啥也不做
                 */
                if(isExist) {
                    return;
                }

                this.books.push({
                    name: bookName
                })
            },
            removeBook() {
                let bookName = this.effectiveJava;
                let index = this.books.findIndex(item => item.name === bookName);

                if(index != -1) {
                    this.books.splice(index, 1);
                }
            },
            popBook() {
                let bookName = this.effectiveJava;
                let index = this.books.findIndex(item => item.name === bookName);

                if(index === 3) {
                    this.books.pop();
                }
            },
            shiftBook() {
                let bookName = this.effectiveJava;
                let index = this.books.findIndex(item => item.name === bookName);

                if(index === 0) {
                    /**
                     * shift() 方法用于把数组的第一个元素从其中删除，并返回第一个元素的值。
                     */
                    this.books.shift();
                }
            },
            unshiftBook() {
                let bookName = this.effectiveJava;
                let isExist = this.books.some(function(item){
                    return item.name === bookName;
                })

                /**
                 * 如果已经存在这本数，就啥也不做
                 */
                if(isExist) {
                    return;
                }

                /**
                 * unshift() 方法可向数组的开头添加一个或更多元素，并返回新的长度。
                 */
                this.books.unshift({
                    name: bookName
                });
            },
            spliceBook() {
                let bookName = this.effectiveJava;
                let isExist = this.books.some(function(item){
                    return item.name === bookName;
                })

                /**
                 * 如果已经存在这本数，就啥也不做
                 */
                if(isExist) {
                    return;
                }

                this.books.splice(2, 0, {name: this.effectiveJava});
            },
            sortBook() {
                this.books.sort(function(a, b){ return a.name.localeCompare(b.name) });
            },
            reverseBook() {
                this.books.reverse();
            },
            /**
             * filter 并不会修改原数组，如果需要更新视图，必须将筛选后的新数组赋值给原数组的变量
             * 好消息：
             * Vue在检测数组变化时，并不是完全重新渲染整个列表，而是最大行的复用DOM元素，替换的数组中
             * 含有相同元素的项不会被重新渲染，因此可以大胆的用新数组替换旧数组，不用担心性能问题。
             */
            filterJavascript() {
                this.books2 = this.books2.filter(function (item) {
                    return item.name.match(/Javascript/);
                })
            },
            /**
             * 尝试使用数组索引直接修改书名，
             * 但是这样的方式变动数组，虽然数组是确实更新了，但Vue是不能检测到的，也不会触发视图更新
             */
            tryChangeBookByIndexNoWork() {
                this.books[2] = "《三体》";
                console.log(JSON.stringify(this.books));
            },
            changeBookByIndex() {
                this.$set(this.books, 2, {
                    name: "《三体》"
                })
            },
            /**
             * 尝试修改数组长度，一般这种方式用于清空数组
             * 但是这样的方式变动数组，虽然数组是确实更新了，但Vue是不能检测到的，也不会触发视图更新
             */
            tryChangeBooksLengthNoWork() {
                this.books.length = 0;
                console.log(JSON.stringify(this.books));
            },
            toggleDblclick() {
                this.toggle();
            },
            toggleChoice() {
                this.choice ++;
                if(this.choice > 3) {
                    this.choice = 1;
                }
            }
        }
    }
</script>